package a12;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestMethodInvoke {
    public static void main(String[] args) throws Exception {
        Method foo = TestMethodInvoke.class.getMethod("foo", int.class);
        for (int i = 1; i <= 17; i++) {
            /**
             * 方法反射调用时，底层用到的是MethodAccessor的实现类，通过show方法把这个类相关的信息打印出来，
             * 可以看到在调用16次以后，这个实现类变了，从NativeMethodAccessorImpl变成了GeneratedMethodAccessor2
             * 利用arthas反编译这个可以看到这个类里是直接不在用反射，而是直接调用的方法。可见底层是做了优化的。
             */
            show(i, foo);
            foo.invoke(null, i);
        }
        System.in.read();
    }

    // 方法反射调用时, 底层 MethodAccessor 的实现类
    private static void show(int i, Method foo) throws Exception {
        Method getMethodAccessor = Method.class.getDeclaredMethod("getMethodAccessor");
        getMethodAccessor.setAccessible(true);
        Object invoke = getMethodAccessor.invoke(foo);
        if (invoke == null) {
            System.out.println(i + ":" + null);
            return;
        }
        //黑马视频的是下面这个jdk.internal包下的，但我的会报错，看弹幕换成sun.reflect就可以呢
//        Field delegate = Class.forName("jdk.internal.reflect.DelegatingMethodAccessorImpl").getDeclaredField("delegate");
        Field delegate = Class.forName("sun.reflect.DelegatingMethodAccessorImpl").getDeclaredField("delegate");

        delegate.setAccessible(true);
        System.out.println(i + ":" + delegate.get(invoke));
    }

    public static void foo(int i) {
        System.out.println(i + ":" + "foo");
    }
}
